/**
  ******************************************************************************
  * @file    usart.c
  * @brief   This file provides code for the configuration
  *          of the USART instances.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"

/* USART2 init function */
void RS485_BspInit(void)
{
	LL_USART_InitTypeDef USART_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2);
  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOD);
	
  /**USART2 GPIO Configuration
  PD4   ------> USART2_DE
  PD5   ------> USART2_TX
  PD6   ------> USART2_RX
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_4;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_5;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /* USART2 interrupt Init */
  NVIC_SetPriority(USART2_IRQn, 3);
  NVIC_EnableIRQ(USART2_IRQn);

  USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
  USART_InitStruct.BaudRate = 19200;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(USART2, &USART_InitStruct);
	
	LL_USART_ConfigAsyncMode(USART2);
  
	LL_USART_SetTXFIFOThreshold(USART2, LL_USART_FIFOTHRESHOLD_1_8);
  LL_USART_SetRXFIFOThreshold(USART2, LL_USART_FIFOTHRESHOLD_1_8);
	LL_USART_DisableFIFO(USART2);
	
	LL_USART_SetRxTimeout(USART2, 576000u);  /* (1/19200)*576 = 30ms */
  LL_USART_EnableRxTimeout(USART2);
	
  LL_USART_SetDESignalPolarity(USART2, LL_USART_DE_POLARITY_HIGH);
  LL_USART_SetDEAssertionTime(USART2, 31);
  LL_USART_SetDEDeassertionTime(USART2, 31);
	LL_USART_EnableDEMode(USART2);
	
	LL_USART_DisableDMADeactOnRxErr(USART2);
  
  LL_USART_DisableInStopMode(USART2);                           /* 低功耗模式下唤醒mcu: disable */
  
	LL_USART_SetWakeUpMethod(USART2, LL_USART_WAKEUP_IDLELINE);   /* uart唤醒方法:空闲线路和地址匹配 */
  LL_USART_DisableMuteMode(USART2);                             /* 关闭uart唤醒功能,始终处于工作模式,若为唤醒模式,则根据上面的唤醒方法 */
  
  LL_USART_SetTXRXSwap(USART2, LL_USART_TXRX_STANDARD);         /* tx rx引脚交换:标准 */
  
  LL_USART_SetTXPinLevel(USART2, LL_USART_TXPIN_LEVEL_STANDARD);
  LL_USART_SetRXPinLevel(USART2, LL_USART_RXPIN_LEVEL_STANDARD);
  LL_USART_SetBinaryDataLogic(USART2, LL_USART_BINARY_LOGIC_POSITIVE);
  
  LL_USART_DisableAutoBaudRate(USART2);
  LL_USART_DisableOneBitSamp(USART2);                           /* 禁止单位采样,采用3位采样 */
  
  LL_USART_DisableHalfDuplex(USART2);
  
  LL_USART_EnableIT_RXNE_RXFNE(USART2);
  LL_USART_EnableIT_RTO(USART2);
	
  LL_USART_Enable(USART2);
  
  LL_USART_RequestRxDataFlush(USART2);
  
  /* Polling USART2 initialisation */
  while((!(LL_USART_IsActiveFlag_TEACK(USART2))) || (!(LL_USART_IsActiveFlag_REACK(USART2))))
  {
  }

	LL_USART_ClearFlag_RTO(USART2);
}

void RS485_Sendbuf(const uint8_t *buf, uint32_t len)
{
	uint32_t i;
	
	for(i=0; i<len; i++)
	{
    USART2->TDR = (buf[i]& (uint16_t)0x01FFU);
    while(READ_BIT(USART2->ISR, USART_ISR_TXE_TXFNF) != (USART_ISR_TXE_TXFNF));
	}
	
	while(READ_BIT(USART2->ISR, USART_ISR_TC) != (USART_ISR_TC));
}

extern void RS485_BreakIsr(void);
extern void RS485_RecvIsr(uint8_t dat);

void USART2_IRQHandler(void)
{
	if(READ_BIT(USART2->ISR, USART_ISR_RXNE_RXFNE) != 0)
	{
		RS485_RecvIsr(USART2->RDR);
	}
  
  if(READ_BIT(USART2->ISR, USART_ISR_RTOF) != 0)
	{
    LL_USART_ClearFlag_RTO(USART2);
		
    RS485_BreakIsr();
  }
  
  if(READ_BIT(USART2->ISR, USART_ISR_ORE) != 0)
	{
    LL_USART_ClearFlag_ORE(USART2);
  }
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
